﻿namespace DimensionsHelper.LanguageService.Syntax;

public abstract class Declaration : Statement, IDeclaration
{
    private readonly SyntaxToken _declareKeywordToken;

    internal Declaration(SyntaxKinds kind, SyntaxToken declareKeywordToken, Identifier name, SyntaxNode? parent) :
        base(kind, parent)
    {
        NameIdentifier = name;

        if (!Expression.IsEmptyExpression(name))
        {
            name.Parent = this;
        }

        _declareKeywordToken = declareKeywordToken;

        if (!SyntaxToken.IsNullOrEmpty(declareKeywordToken))
        {
            declareKeywordToken.Parent = this;
        }
    }

    protected virtual bool WithoutDeclareKeywordToken => false;

    protected virtual bool WithoutNameIdentifier => false;


    /// <summary>
    ///     声明的名称
    /// </summary>
    public Identifier NameIdentifier { get; }


    public virtual bool IsMetadata => false;


    /// <summary>
    ///     如果此声明是函数、类方法或者类属性中的参数，返回true。
    /// </summary>
    public bool IsParameter
    {
        get
        {
            if (IsNode(SyntaxKinds.ParameterSignature))
            {
                return true;
            }

            if (Parent != null &&
                Parent.IsNode(SyntaxKinds.FunctionDeclaration))
            {
                return IsOneOfNode(SyntaxKinds.VariableDeclaration, SyntaxKinds.ArrayDeclaration);
            }

            return false;
        }
    }


    /// <summary>
    ///     如果此声明被使用了，将此属性设置为true。
    /// </summary>
    public bool IsDeclarationUsed { get; internal set; }


    public string FullName => GetFullName();


    ITextNode IDeclaration.NameIdentifier => NameIdentifier;


    public virtual string Name => NameIdentifier.Value;


    public virtual bool IsSignature => false;

    public virtual bool IsTypeSignature => false;


    public ITextNode DeclareKeywordToken => _declareKeywordToken;


    public virtual bool ContainsModifier(SyntaxKinds kind)
    {
        return false;
    }

    public virtual bool ContainsAnyModifier(params SyntaxKinds[] modifiersKinds)
    {
        return false;
    }


    public override void AcceptVisitor<T>(SyntaxNodeVisitor<T> visitor)
    {
        if (!WithoutDeclareKeywordToken)
        {
            Accept(visitor, DeclareKeywordToken);
        }

        if (!WithoutNameIdentifier)
        {
            Accept(visitor, NameIdentifier);
        }

        base.AcceptVisitor(visitor);
    }


    protected virtual string GetFullName()
    {
        return Name;
    }


    protected static T? FindDeclaration<T>(SyntaxList<T>? list, string name) where T : class, IDeclaration
    {
        return list?.Find(member => member.Name.Equals(name, StringComparison.OrdinalIgnoreCase));
    }
}